package com.zwps.biz.domain.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.zwps.biz.domain.converter.PagePermissionConverter;
import com.zwps.biz.domain.service.PagePermissionService;
import com.zwps.biz.domain.tool.TreeCodeTool;
import com.zwps.biz.api.model.dto.permission.page.AddPagePermissionDTO;
import com.zwps.biz.api.model.dto.permission.page.SelectPagePermissionDTO;
import com.zwps.biz.api.model.dto.permission.page.UpdatePagePermissionDTO;
import com.zwps.biz.api.model.vo.permission.page.PagePermissionTreeVO;
import com.zwps.biz.dal.db.dao.PagePermissionDAO;
import com.zwps.biz.dal.db.dao.RolePagePermissionDAO;
import com.zwps.biz.dal.db.object.PagePermissionDO;
import com.zwps.biz.dal.db.object.RolePagePermissionDO;
import com.zwps.common.core.exception.UserActionException;
import com.zwps.common.core.service.CommonService;
import com.zwps.common.tool.tree.TreeTool;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
import java.util.function.Function;

@AllArgsConstructor
@Slf4j
@Service
public class PagePermissionServiceImpl implements PagePermissionService, CommonService {

    private PagePermissionDAO pagePermissionDAO;

    private RolePagePermissionDAO rolePagePermissionDAO;
    
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void addPagePermission(AddPagePermissionDTO dto) {
        String parentTreeCode = null;
        if (StrUtil.isNotEmpty(dto.getParentId())) {
            PagePermissionDO permission = pagePermissionDAO.selectById(dto.getParentId());
            if (permission == null) {
                throw new UserActionException("上级不存在或已被删除");
            }
            parentTreeCode = permission.getTreeCode();
        }
        PagePermissionDO sortLast = findLastPagePermission(dto.getParentId());

        String treeCode = TreeCodeTool.generateIncremental(parentTreeCode,
                sortLast == null ? null : sortLast.getTreeCode());

        PagePermissionDO pagePermission = PagePermissionConverter.INSTANCE.toPagePermissionDO(dto);
        pagePermission.setTreeCode(treeCode);
        if (pagePermissionDAO.insert(pagePermission) < 1) {
            throw new UserActionException("新增页面权限失败");
        }
    }

    /**
     * 获取指定下通过treeCode排序，返回最后一个数据
     * 
     * @Title: findLastPagePermission
     * @Description:
     * @param parentId
     * @return PagePermissionDO
     * @author lyh
     * @date 2023年5月22日 下午2:29:00
     */
    public PagePermissionDO findLastPagePermission(String parentId) {
        LambdaQueryWrapper<PagePermissionDO> countDeptQuery = Wrappers.lambdaQuery(PagePermissionDO.class);
        if (StrUtil.isEmpty(parentId)) {
            countDeptQuery.eq(PagePermissionDO::getParentId, parentId);
            countDeptQuery.or().isNull(PagePermissionDO::getParentId);
        } else {
            countDeptQuery.eq(PagePermissionDO::getParentId, parentId);
        }
        countDeptQuery.last(" ORDER BY replace(tree_code,'" + TreeCodeTool.TREE_CODE_TAG + "', '')+0 desc limit 1");
        return pagePermissionDAO.selectOne(countDeptQuery);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deletePagePermissions(String ids) {

        List<String> idList = Arrays.asList(ids.split(","));
        int result = pagePermissionDAO.deleteBatchIds(Arrays.asList(ids.split(",")));
        if (result != idList.size()) {
            long PagePermissionNum = pagePermissionDAO
                    .selectCount(Wrappers.lambdaQuery(PagePermissionDO.class).in(PagePermissionDO::getId, idList));
            if (PagePermissionNum > 0) {
                log.error("Delete Page Permissions id[{}] fail, select item {}, delete success {}", ids, idList.size(),
                        result);
                throw new UserActionException("删除失败");
            }
        }
        rolePagePermissionDAO.delete(Wrappers.lambdaQuery(RolePagePermissionDO.class).in(RolePagePermissionDO::getPagePermissionId, idList));
    }

    public String updateParentCheck(PagePermissionDO selectdPagePermission, String parentId,
            LambdaUpdateWrapper<PagePermissionDO> update) {
        String parentTreeCode = "";
        if (StrUtil.isEmpty(parentId)) {
            return null;
        }
        if (parentId.equals(selectdPagePermission.getId())) {
            throw new UserActionException("不能选择自己作为上级");
        }

        PagePermissionDO selectdParent = pagePermissionDAO.selectById(parentId);
        if (selectdParent == null) {
            throw new UserActionException("更新后的上级不存在");
        }

        if (selectdParent.getTreeCode().startsWith(selectdPagePermission.getTreeCode())) {
            throw new UserActionException("不能选择子集部门作为上级");
        }

        parentTreeCode = selectdParent.getTreeCode();
        update.set(PagePermissionDO::getParentId, parentId);

        PagePermissionDO sortLast = findLastPagePermission(parentId);

        String treeCode = TreeCodeTool.generateIncremental(parentTreeCode,
                sortLast == null ? null : sortLast.getTreeCode());
        update.set(PagePermissionDO::getTreeCode, treeCode);
        return treeCode;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updatePagePermission(String id, UpdatePagePermissionDTO dto) {
        PagePermissionDO selectd = pagePermissionDAO.selectById(id);
        if (selectd == null) {
            throw new UserActionException("修改的页面权限不存在");
        }

        LambdaUpdateWrapper<PagePermissionDO> update = Wrappers.lambdaUpdate(PagePermissionDO.class);

        String treeCode = updateParentCheck(selectd, dto.getParentId(), update);
        update.set(change(dto.getIcon(), selectd.getIcon()), PagePermissionDO::getIcon, dto.getIcon());
        update.set(change(dto.getComponent(), selectd.getComponent()), PagePermissionDO::getComponent, dto.getComponent());
        update.set(change(dto.getType(), selectd.getType()), PagePermissionDO::getType, dto.getType());
        update.set(change(dto.getMenuName(), selectd.getMenuName()), PagePermissionDO::getMenuName, dto.getMenuName());
        update.set(change(dto.getPermission(), selectd.getPermission()), PagePermissionDO::getPermission, dto.getPermission());
        update.set(change(dto.getOrderNo(), selectd.getOrderNo()), PagePermissionDO::getOrderNo, dto.getOrderNo());
        update.set(change(dto.getStatus(), selectd.getStatus()), PagePermissionDO::getStatus, dto.getStatus());
        update.set(change(dto.getShowMenu(), selectd.getShowMenu()), PagePermissionDO::getShowMenu, dto.getShowMenu());
        update.set(change(dto.getIgnoreKeepAlive(), selectd.getIgnoreKeepAlive()), PagePermissionDO::getIgnoreKeepAlive, dto.getIgnoreKeepAlive());
        update.set(change(dto.getFrameUrl(), selectd.getFrameUrl()), PagePermissionDO::getFrameUrl, dto.getFrameUrl());
        update.set(change(dto.getPath(), selectd.getPath()), PagePermissionDO::getPath, dto.getPath());
        update.set(change(dto.getCurrentActiveMenu(), selectd.getCurrentActiveMenu()), PagePermissionDO::getCurrentActiveMenu, dto.getCurrentActiveMenu());
        update.set(change(dto.getShowFrame(), selectd.getShowFrame()), PagePermissionDO::getShowFrame, dto.getShowFrame());
        update.set(change(dto.getTreeCode(), selectd.getTreeCode()), PagePermissionDO::getTreeCode, dto.getTreeCode());
        update.set(change(dto.getParentId(), selectd.getParentId()), PagePermissionDO::getParentId, dto.getParentId());

        if (StrUtil.isNotEmpty(update.getSqlSet())) {
            update.eq(PagePermissionDO::getId, id);
            if (pagePermissionDAO.update(null, update) < 1) {
                throw new UserActionException("修改页面权限信息失败");
            }
        }
        // 这里修改要在当前修改之后，如果当前数据的上级ID是置空，可能会出现treeCode违反唯一约束
        if (treeCode != null) {
            // 可能不存在子集，所以不作修改条数判断
            pagePermissionDAO.updateChildrenTreeCode(selectd.getTreeCode(), treeCode, TreeCodeTool.TREE_CODE_TAG);
        }
    }

    @Override
    public List<PagePermissionDO> selectPagePermissions(SelectPagePermissionDTO dto) {
        LambdaQueryWrapper<PagePermissionDO> query = Wrappers.lambdaQuery(PagePermissionDO.class);
        query.like(StrUtil.isNotEmpty(dto.getName()), PagePermissionDO::getMenuName, dto.getName());
//        query.like(StrUtil.isNotEmpty(dto.getUrl()), PagePermissionDO::getUrl, dto.getUrl());
//        query.like(StrUtil.isNotEmpty(dto.getComponentUrl()), PagePermissionDO::getComponentUrl, dto.getComponentUrl());
//        query.eq(dto.getRoute() != null, PagePermissionDO::getRoute, dto.getRoute());
//        query.like(StrUtil.isNotEmpty(dto.getComponentName()), PagePermissionDO::getComponentName, dto.getComponentName());
//        query.like(StrUtil.isNotEmpty(dto.getRedirect()), PagePermissionDO::getRedirect, dto.getRedirect());
//        query.eq(dto.getPermissionType() != null, PagePermissionDO::getPermissionType, dto.getPermissionType());
//        query.like(StrUtil.isNotEmpty(dto.getPermissionCode()), PagePermissionDO::getPermissionCode, dto.getPermissionCode());
//        query.like(StrUtil.isNotEmpty(dto.getDisplayStrategy()), PagePermissionDO::getDisplayStrategy, dto.getDisplayStrategy());
//        query.eq(dto.getSort() != null, PagePermissionDO::getSort, dto.getSort());
//        query.like(StrUtil.isNotEmpty(dto.getIcon()), PagePermissionDO::getIcon, dto.getIcon());
//        query.eq(dto.getKeepAlive() != null, PagePermissionDO::getKeepAlive, dto.getKeepAlive());
//        query.eq(dto.getHiddenRoute() != null, PagePermissionDO::getHiddenRoute, dto.getHiddenRoute());
//        query.eq(dto.getHiddenTab() != null, PagePermissionDO::getHiddenTab, dto.getHiddenTab());
//        query.like(StrUtil.isNotEmpty(dto.getDescription()), PagePermissionDO::getDescription, dto.getDescription());
        query.orderByAsc(PagePermissionDO::getOrderNo);
        return pagePermissionDAO.selectList(query);
    }
    
    @Override
    public List<PagePermissionTreeVO> findTree(String parentId) {
        LambdaQueryWrapper<PagePermissionDO> deptQuery = Wrappers.lambdaQuery(PagePermissionDO.class);
        if (StrUtil.isNotEmpty(parentId)) {
            PagePermissionDO permission = pagePermissionDAO.selectById(parentId);
            if (permission == null) {
                throw new UserActionException("查询指定的菜单不存在");
            }
            deptQuery.and((a -> {
                a.eq(PagePermissionDO::getParentId, parentId).or().likeRight(PagePermissionDO::getTreeCode,
                        permission.getTreeCode());
            }));
        }
       return toTree(pagePermissionDAO.selectList(deptQuery));
    }
    
    @Override
    public  List<PagePermissionTreeVO> findTreeByTreeCodes(Collection<String> treeCodes) {
        LambdaQueryWrapper<PagePermissionDO> deptQuery = Wrappers.lambdaQuery(PagePermissionDO.class);
        deptQuery.in(PagePermissionDO::getTreeCode, treeCodes);
        return toTree(pagePermissionDAO.selectList(deptQuery));
    }
    
    private List<PagePermissionTreeVO> toTree(List<PagePermissionDO> list) {
        if (list.isEmpty()) {
            return CollUtil.newArrayList();
        }
        Function<PagePermissionDO, PagePermissionTreeVO> treeInstance = (a) -> {
            return PagePermissionConverter.INSTANCE.toPagePermissionTreeVO(a);
        };

        return TreeTool.build(list, treeInstance, (a) -> a.getId(), (a) -> a.getParentId(), (a) -> a.getMenuName(),
                (a) -> a.getOrderNo());
    }
}
